﻿
namespace Behemoth.SharePoint.ContentTypes {

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Text;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Utilities;

    using Behemoth.Configuration;
    using Behemoth.SharePoint.Logging;

    /// <summary>
    /// This receiver updates a content type or site columns using
    /// the element file, but also ensures that the API is called so
    /// that the type is "unghosted" and the database will have the
    /// same definition as the Xml in the feature folder.
    /// </summary>
    /// <remarks>
    /// ReceiverAssembly="Behemoth.SharePoint.ARK, Version=1.?.?.?, Culture=neutral, PublicKeyToken=ecab56691def8148"
    /// ReceiverClass="Behemoth.SharePoint.ContentTypes.ContentTypeUpdateReceiver"
    /// </remarks>
    public class ContentTypeUpdateReceiver : SPFeatureReceiver {
        
        private ContentTypeUpdateProperties recvProps;
        private ContentTypeUpdateProperties TypedProperties {
            get { return recvProps; }
        }

        private void EnsureProperties(SPFeatureReceiverProperties properties) {
            WriteLog("Invoking EnsureProperties.");
            if (recvProps == null)
                recvProps = new ContentTypeUpdateProperties(properties);
            else if (recvProps.InitStatus != Status.Initialized)
                throw new Exception("property reader is not initialized. Can't continue.");
            WriteLog("Leaving EnsureProperties.");
        }

        [SuppressMessage("Microsoft.Design", "CA1041:ProvideObsoleteAttributeMessage", Justification = "Use of SPContentTypeFeatureTools is provided for backward compatibility, and appropriate docuemntation has been added to the caller.")]
        protected void RefreshListContentTypes(object web, ListContentTypeRefreshEventArgs args) {
            args.ForceUpdate = this.TypedProperties.ListContentTypeForceUpdate;
            args.RecurseSubWebs = this.TypedProperties.ListContentTypeRecurseSubWebs;
            args.UseTimerJob = this.TypedProperties.ListContentTypeUseTimerJob;
            args.UpdateFields = true; // TODO make configurable?
            args.RemoveFields = false; // TODO make configurable?
#if LegacyXmlContentTypeFunctions
            if (this.TypedProperties.UseXmlLinqMethods)
                SPContentTypeFeatureToolsX.DoRefreshListContentTypes(web, args);
            else
                SPContentTypeFeatureTools.DoRefreshListContentTypes(web, args);
#else
            SPContentTypeFeatureToolsX.DoRefreshListContentTypes(web, args);
#endif
        }

        [SuppressMessage("Microsoft.Design", "CA1041:ProvideObsoleteAttributeMessage", Justification = "Use of SPContentTypeFeatureTools is provided for backward compatibility, and appropriate docuemntation has been added to the caller.")]
        public override void FeatureActivated(SPFeatureReceiverProperties properties) {
            EnsureProperties(properties);
            if (this.TypedProperties.CreateSiteColumnsByWebService) {
                WriteLog("Entering EnsureSiteColumns.");
#if LegacyXmlContentTypeFunctions
                if (this.TypedProperties.UseXmlLinqMethods) {
                    SPContentTypeFeatureToolsX.EnsureSiteColumns(this.TypedProperties.Site.RootWeb, this.TypedProperties.SiteColumnElementFilePath);
                } else {
                    SPContentTypeFeatureTools.EnsureSiteColumns(this.TypedProperties.Site.RootWeb, this.TypedProperties.SiteColumnElementFilePath);
                }
#else
                SPContentTypeFeatureToolsX.EnsureSiteColumns(this.TypedProperties.Site.RootWeb, this.TypedProperties.SiteColumnElementFilePath);
#endif
                WriteLog("Leaving EnsureSiteColumns.");
            }
            if (this.TypedProperties.UpdateContentTypesByWebService) {
                WriteLog("Entering EnsureContentTypes.");
#if LegacyXmlContentTypeFunctions
                    if (this.TypedProperties.UseXmlLinqMethods) {
                        SPContentTypeFeatureToolsX.RemoveAllRefreshListContentTypes();
                        if (this.TypedProperties.EnableRefreshListContentTypes) {
                            SPContentTypeFeatureToolsX.RefreshListContentTypes += new ListContentTypeRefreshEventHandler(RefreshListContentTypes);
                        }                
                        SPContentTypeFeatureToolsX.EnsureContentTypes(this.TypedProperties.Site.RootWeb, this.TypedProperties.ContentTypeElementFilePath);
                    } else {
                        SPContentTypeFeatureTools.RemoveAllRefreshListContentTypes();
                        if (this.TypedProperties.EnableRefreshListContentTypes) {
                            SPContentTypeFeatureTools.RefreshListContentTypes += new ListContentTypeRefreshEventHandler(RefreshListContentTypes);
                        }
                        SPContentTypeFeatureTools.EnsureContentTypes(this.TypedProperties.Site.RootWeb, this.TypedProperties.ContentTypeElementFilePath);
                    }
#else
                SPContentTypeFeatureToolsX.RemoveAllRefreshListContentTypes();
                    if (this.TypedProperties.EnableRefreshListContentTypes) {
                        SPContentTypeFeatureToolsX.RefreshListContentTypes += new ListContentTypeRefreshEventHandler(RefreshListContentTypes);
                    }
                    SPContentTypeFeatureToolsX.EnsureContentTypes(this.TypedProperties.Site.RootWeb, this.TypedProperties.ContentTypeElementFilePath);
#endif
                WriteLog("Leaving EnsureContentTypes.");
            }
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {
            //EnsureProperties(properties);
            //throw new Exception("The method or operation is not implemented.");
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties) {
            //EnsureProperties(properties);
            //throw new Exception("The method or operation is not implemented.");
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties) {
            //EnsureProperties(properties);
            //throw new Exception("The method or operation is not implemented.");
        }

        // TODO make an event model or something that works better than this does....
        #region Logging Code Pattern

        private ULSTraceLogging logWriter;

        private void EnsureLogWriter() {
            if (logWriter != null)
                return;
            logWriter = new ULSTraceLogging();
            // also ensure that anything we put to the trace also gets logged to ULS
            //TODO: actually this does not seem to be working as intended, so we still log and trace seperately.
            //SharepointTraceListener.EnsureListener(true, true);
        }
        private void WriteLog(string text) {
            EnsureLogWriter();
            logWriter.Write(text);
            Trace.WriteLine(text);
        }
        private void WriteLog(Exception ex) {
            EnsureLogWriter();
            logWriter.Write(ex);
            Trace.WriteLine(ex);
        }
        private void WriteLog(object textOrException) {
            Exception ex = textOrException as Exception;
            if (ex != null)
                WriteLog(ex);
            else
                WriteLog(textOrException.ToString());
        }

        #endregion

    } // class
} // namespace
